<?php

class Jf_Session_Session implements Jf_Session_Interface {

    const NAMESPACE_DEFAULT = 'jf_cart';

    const MEMBER_DEFAULT = 'storage';

    protected $_session;

    protected $_namespace;

    public function __construct ($namespace = self::NAMESPACE_DEFAULT) {
        $this -> _namespace = sha1 ($namespace);
        $this -> _session = $this -> getSession ();
    }

    public function getNamespace () {
        return $this -> _namespace;
    }

    protected function getSession () {
        if ( ! isset ($_SESSION)) {
            session_start ();
        }
        if ($this -> isEmpty ()) {
            $this -> _session[$this -> _namespace] = new stdClass ();
            $this -> _session[$this -> _namespace] -> items = array();
            $this -> save ();
        }
        return unserialize (stripslashes ($_SESSION[$this -> _namespace]));
    }

    public function isEmpty () {
        return  ! isset ($_SESSION[$this -> _namespace]) || $_SESSION[$this -> _namespace] == 'a:0:{}';
    }

    public function get ($keys) {
        $keys =  ! empty ($keys) ? explode ('.', $keys) : false;
        $res = array();
        if (count ($keys) > 0) {
            $this -> _session[$this -> _namespace] -> items[$keys[0]] = isset ($this -> _session[$this -> _namespace] -> items[$keys[0]]) ? $this -> _session[$this -> _namespace] -> items[$keys[0]] : array();
            $tmp = &$this -> _session[$this -> _namespace] -> items[$keys[0]];
            foreach ($keys as $k => $v) {
                if ($k == 0) {
                    continue;
                } else {
                    $tmp[$v] = isset ($tmp[$v]) ? $tmp[$v] : array();
                    $tmp = &$tmp[$v];
                }
            }
            $res = $tmp;
        }
        return $res;
    }

    public function getAll () {
        return isset ($this -> _session[$this -> _namespace] -> items) ? $this -> _session[$this -> _namespace] -> items : array();
    }

    public function set ($keys, $value) {
        $keys =  ! empty ($keys) ? explode ('.', $keys) : false;
        if (count ($keys) > 0) {
            $this -> _session[$this -> _namespace] -> items[$keys[0]] = isset ($this -> _session[$this -> _namespace] -> items[$keys[0]]) ? $this -> _session[$this -> _namespace] -> items[$keys[0]] : array();
            $tmp = &$this -> _session[$this -> _namespace] -> items[$keys[0]];
            foreach ($keys as $k => $v) {
                if ($k == 0) {
                    continue;
                } else {
                    $tmp[$v] = isset ($tmp[$v]) ? $tmp[$v] : array();
                    $tmp = &$tmp[$v];
                }
            }
            $tmp = $value;
            $this -> save ();
        }
    }

    public function setAttr ($key, $value) {
        $this -> _session[$this -> _namespace] -> items[$key] = array_merge (isset ($this -> _session[$this -> _namespace] -> items[$key]) ? $this -> _session[$this -> _namespace] -> items[$key] : array(), $value);
        $this -> save ();
    }

    public function remove ($keys) {
        $keys =  ! empty ($keys) ? explode ('.', $keys) : false;
        if (count ($keys) > 0) {
            $this -> _session[$this -> _namespace] -> items[$keys[0]] = isset ($this -> _session[$this -> _namespace] -> items[$keys[0]]) ? $this -> _session[$this -> _namespace] -> items[$keys[0]] : array();
            $tmp = '$this->_session[$this->_namespace]->items';
            foreach ($keys as $v) {
                $tmp .= "['$v']";
            }
            eval ("unset($tmp);");
            $this -> save ();
        }
    }

    public function removeAttr ($key, $attrs = array()) {
        foreach ($this -> _session[$this -> _namespace] -> items[$key] as $k => $v) {
            if (in_array ($k, $attrs))
                unset ($this -> _session[$this -> _namespace] -> items[$key][$k]);
        }
        $this -> save ();
    }

    public function clear () {
        unset ($this -> _session[$this -> _namespace] -> items);
        $this -> save ();
    }

    public function clearAll () {
        unset ($this -> _session[$this -> _namespace]);
        $this -> save ();
    }

    public function save () {
        $_SESSION[$this -> _namespace] = addslashes (serialize ($this -> _session));
    }

}
